package com.cgc.venus.server.core.heapster;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.squareup.okhttp.*;
import com.cgc.venus.server.core.bean.response.VenusResponseStatus;
import com.cgc.venus.server.core.exception.VenusException;
import com.cgc.venus.server.core.heapster.model.ResultPair;
import com.cgc.venus.server.core.heapster.model.ResultSet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.net.ssl.*;
import java.io.IOException;
import java.net.CookieManager;
import java.security.cert.CertificateException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
@ConfigurationProperties(prefix = "heapster")
public class HeapsterClient {
    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private OkHttpClient okhttpClient;
    private ObjectMapper mapper = new ObjectMapper();
    private String baseUrl;
    private boolean verifySSL = false;
    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }
    private CookieManager cookieManager;

    public CookieManager getCookieManager() {
        return cookieManager;
    }
    /**
     *
     */
    public HeapsterClient() {
        getOkHttpClient();
    }
    /**
     * @param baseUrl
     */
    public HeapsterClient(String baseUrl) {
        this(baseUrl, false);
    }

    /**
     * @param baseUrl
     * @param verifySSL
     */
    public HeapsterClient(String baseUrl, boolean verifySSL) {
        this.baseUrl = baseUrl;
        this.verifySSL = verifySSL;
        getOkHttpClient();
    }

    /**
     * append '/' to baseUrl if it doesn't end with '/'
     *
     * @return
     */
    private String getBaseUrl() {
        if (!this.baseUrl.endsWith("/")) {
            this.baseUrl += "/";
        }
        return this.baseUrl;
    }

    /**
     * 获取OkHttpClient
     *
     * @return
     */
    private void getOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
                        throws CertificateException {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
                        throws CertificateException {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[0];
                }
            }};
            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            okhttpClient = new OkHttpClient();
            okhttpClient.setSslSocketFactory(sslSocketFactory);
            okhttpClient.setHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession sslSession) {
                    return !HeapsterClient.this.verifySSL;
                }
            });
            cookieManager = new CookieManager();
            okhttpClient.setCookieHandler(cookieManager);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 基础查询
     * @param url
     * @return
     * @throws VenusException
     */
    private ResultSet search(String url)throws VenusException{
        Request request = new Request.Builder().url(url).get().build();
        Response response = null;
        try {
            response = okhttpClient.newCall(request).execute();
        } catch (IOException e) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, e.getMessage());
        }
        int code = response.code();
        if (code != 200) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, "调用heapster api异常!");
        }
        ResultSet rs=null;
        try {
            rs = mapper.readValue(response.body().string(), ResultSet.class);
        } catch (IOException e) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, e.getMessage());
        }
        return rs;
    }

    /**
     * 查询
     * 时间格式 : 2017-11-10T07:39:00Z   yyyy-MM-dd'T'HH:mm:ss'Z'
     * @param url
     * @return
     * @throws VenusException
     */
    private ResultSet search(String url,String start,String end)throws VenusException{
        //测试用----start
//        boolean f=true;
//        if(f){
//            ResultSet rs=new ResultSet();
//            List<ResultPair> metrics=new ArrayList<ResultPair>();
//            ResultPair rp=new ResultPair();
//            Random random = new Random();
//            rp.setTimestamp("2017-11-16T01:26:00Z");
//            rp.setValue(random.nextInt(40000));
//            metrics.add(rp);
//            rp=new ResultPair();
//            rp.setTimestamp("2017-11-16T01:27:00Z");
//            rp.setValue(random.nextInt(40000));
//            metrics.add(rp);
//            rp=new ResultPair();
//            rp.setTimestamp("2017-11-16T01:28:00Z");
//            rp.setValue(random.nextInt(40000));
//            metrics.add(rp);
//            rp=new ResultPair();
//            rp.setTimestamp("2017-11-16T01:29:00Z");
//            rp.setValue(random.nextInt(40000));
//            metrics.add(rp);
//            rs.setMetrics(metrics);
//            return rs;
//        }
        //测试用----end

        url=url+"?start="+start+"&end="+end;
        Request request = new Request.Builder().url(url).get().build();
        Response response = null;
        try {
            response = okhttpClient.newCall(request).execute();
        } catch (IOException e) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, e.getMessage());
        }
        int code = response.code();
        if (code != 200) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, "调用heapster api异常!");
        }
        ResultSet rs=null;
        try {
            rs = mapper.readValue(response.body().string(), ResultSet.class);
        } catch (IOException e) {
            throw new VenusException(VenusResponseStatus.MONITOR_EXCEPTION, e.getMessage());
        }
        return rs;
    }



    public ResultSet clusterSearch(MetricsType metricsType) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/metrics/" + metricsType.getName();
        return search(url);
    }


    public ResultSet clusterSearch(MetricsType metricsType,String start,String end) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/metrics/" + metricsType.getName();
        return search(url,start,end);
    }


    public ResultPair clusterSearchByCurrentValue(MetricsType metricsType) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/metrics/" + metricsType.getName();
        ResultSet rs= search(url);
        List<ResultPair> rps=rs.getMetrics();
        if(rps!=null&&rps.size()>0){
           return rps.get(rps.size()-1);
        }
        return null;
    }

    //node
    public ResultSet nodeSearch(MetricsType metricsType,String  nodeName) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/nodes/"+nodeName+"/metrics/" + metricsType.getName();
        return search(url);
    }


    public ResultSet nodeSearch(MetricsType metricsType,String  nodeName,String start,String end) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/nodes/"+nodeName+"/metrics/" + metricsType.getName();
        return search(url,start,end);
    }


    public ResultPair nodeSearchByCurrentValue(MetricsType metricsType,String  nodeName) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/nodes/"+nodeName+"/metrics/" + metricsType.getName();
        ResultSet rs= search(url);
        List<ResultPair> rps=rs.getMetrics();
        if(rps!=null&&rps.size()>0){
            return rps.get(rps.size()-1);
        }
        return null;
    }

    //namespace
    public ResultSet namespaceSearch(MetricsType metricsType,String  namespace) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/metrics/" + metricsType.getName();
        return search(url);
    }


    public ResultSet namespaceSearch(MetricsType metricsType,String  namespace,String start,String end) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/metrics/" + metricsType.getName();
        return search(url,start,end);
    }


    public ResultPair namespaceSearchByCurrentValue(MetricsType metricsType,String  namespace) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/metrics/" + metricsType.getName();
        ResultSet rs= search(url);
        List<ResultPair> rps=rs.getMetrics();
        if(rps!=null&&rps.size()>0){
            return rps.get(rps.size()-1);
        }
        return null;
    }

    //pod
    public ResultSet podSearch(MetricsType metricsType,String  namespace,String podName) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/pods/"+podName+"/metrics/" + metricsType.getName();
        return search(url);
    }


    public ResultSet podSearch(MetricsType metricsType,String  namespace,String podName,String start,String end) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/pods/"+podName+"/metrics/" + metricsType.getName();
        return search(url,start,end);
    }


    public ResultPair podSearchByCurrentValue(MetricsType metricsType,String  namespace,String podName) throws VenusException {
        String url = getBaseUrl() + "api/v1/model/namespaces/"+namespace+"/pods/"+podName+"/metrics/" + metricsType.getName();
        ResultSet rs= search(url);
        List<ResultPair> rps=rs.getMetrics();
        if(rps!=null&&rps.size()>0){
            return rps.get(rps.size()-1);
        }
        return null;
    }

    //RFC-3339
    public static void main(String[] args){
        String STANDARD_DATE_FORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'";
        Calendar date = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat(STANDARD_DATE_FORMAT_UTC);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        Date dateTime = null;
        try {
            dateTime = sdf.parse("2017-11-08T12:11:00Z");
        } catch (ParseException e) {
            e.printStackTrace();
        }
       SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf1.format(dateTime));



//        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
//        try {
//
//            String str=sdf.format(new Date());
//            System.out.println(str);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

    }
}